﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
using System.Diagnostics;
using BingVis.Common;
using System.ComponentModel;

namespace BingVis.GoogleTransit
{
    public static class FareFileCompressor
    {
        private static Action<string> _finishedCallback;
        private static BackgroundWorker _compressorWorker;

        static FareFileCompressor()
        {
            _compressorWorker = new BackgroundWorker();
            _compressorWorker.WorkerReportsProgress = false;
            _compressorWorker.WorkerSupportsCancellation = false;
            _compressorWorker.DoWork += new DoWorkEventHandler(Compressor_DoWork);
            _compressorWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Compressor_Completed);
        }

        private static void Compressor_DoWork(object sender, DoWorkEventArgs e)
        {
            var args = e.Argument as CompressArgs;
            var file = new GTFSFile(args.FareFilePath);
            var loader = new FareTapLoader(file);
            loader.ProcessFile();
            while (loader.Processing) 
            {
                // TODO: Report Progress?
                Thread.Sleep(1000);                 
            }

            StringBuilder sb = new StringBuilder();

            // Group by stop name
            foreach (var stopFares in loader.Items.GroupBy(x => FareStopLookup.GetStopName(x.StopName)))
            {
                sb.Append(FareStopLookup.GetStopName(stopFares.First().StopName));
                // Group fares by quarter hour.
                foreach (var quarterFares in stopFares.GroupBy(y => y.Time.GetQuarterHour()))
                {
                    sb.AppendFormat(",{0:g}|{1:0.00}", quarterFares.First().Time.GetQuarterHour(), quarterFares.Sum(qf => qf.Amount));
                }
                sb.AppendLine();
            }

            File.WriteAllText(args.CompressedFilePath, sb.ToString());
            e.Result = args.CompressedFilePath;
        }

        private static void Compressor_Completed(object sender, RunWorkerCompletedEventArgs args)
        {
            if (args.Error != null)
                throw args.Error;

            if ( _finishedCallback != null )
                _finishedCallback(args.Result as string);
        }

        private class CompressArgs
        {
            public string FareFilePath { get; private set; }
            public string CompressedFilePath { get; private set; }
            public CompressArgs(string ffp, string cfp)
            {
                FareFilePath = ffp;
                CompressedFilePath = cfp;
            }
        }

        public static void CompressFareFile(string fareFileFullPath, string compressedFileFullPath, Action<string> finishedCallback)
        {
            if (!File.Exists(fareFileFullPath))
                throw new ArgumentException("Specified Fare File does not exist");

            _finishedCallback = finishedCallback;
            _compressorWorker.RunWorkerAsync(new CompressArgs(fareFileFullPath, compressedFileFullPath));
        }

    }
}
